<?php
/**
 * 周舟 hzboye010@163.com
 * addby sublime snippets
 * 微信支付支持
 */

namespace Api\Controller;

use Api\Controller\ApiController;
// use Think\Controller;

class WxpayController extends ApiController{
	protected $config = array();
	  /**
     * 构造函数
     */
    public function __construct(){
        parent::__construct();
        // $this->getConfig();
    }
	/**
	 * [setConfig description]
	 * @param [type] $config [description]
	 */
	protected function setConfig($config){
	    $this->config = $config;
	}

    /**
    * only for test
    * @param  [type] $str [description]
    * @return [type]      [description]
    */
    // public function log($str){
    //     file_put_contents('log.bak', $str.PHP_EOL, FILE_APPEND);
    // }
    /**
     * ajax返回
     * @param $data
     * @internal param $i
     */
    protected function apiReturnSuc($data){
        header('Content-Type:application/json; charset=utf-8');
        exit(json_encode(array('code'=>0,'data'=>$data,'notify_id'=>$this->notify_id),false));
    }

    /**
     * ajax返回，并自动写入token返回
     * @param $data
     * @param int $code
     * @internal param $i
     */
    protected function apiReturnErr($data,$code=-1){
        header('Content-Type:application/json; charset=utf-8');
        exit(json_encode(array('code'=>$code,'data'=>$data,'notify_id'=>$this->notify_id),false));
    }

    /**
     * get config by C()
     * @return [type] [description]
     */
 //  protected function getConfig() {
	// 	$config = S('config_' . session_id() . '_' . session("uid"));
	// 	if ($config === false) {
	// 		//		if (APP_DEBUG === true) {
	// 		//			//调试模式下，不缓存配置
	// 		//			$config = false;
	// 		//		}
	// 		$map = array();
	// 		$fields = 'type,name,value';
	// 		$result = apiCall('Admin/Config/queryNoPaging', array($map, false, $fields));
	// 		if ($result['status']) {
	// 			$config = array();
	// 			if (is_array($result['info'])) {
	// 				// dump($result['info']);exit;
	// 				foreach ($result['info'] as $value) {
	// 					$config[$value['name']] = $this -> parse($value['type'], $value['value']);
	// 				}
	// 			}
	// 			//缓存配置300秒
	// 			S("config_" . session_id() . '_' . session("uid"), $config, 300);
	// 		} else {
	// 			LogRecord('INFO:' . $result['info'], '[FILE] ' . __FILE__ . ' [LINE] ' . __LINE__);
	// 			$this -> error($result['info']);
	// 		}
	// 	}
	// 	C($config);
	// }
	/**
	 * 根据配置类型解析配置
	 * @param  integer $type  配置类型
	 * @param  string  $value 配置值
	 */
	// protected static function parse($type, $value) {
	// 	switch ($type) {
	// 		case 3 :
	// 			//解析数组
	// 			$array = preg_split('/[,;\r\n]+/', trim($value, ",;\r\n"));
	// 			if (strpos($value, '=')) {
	// 				$value = array();
	// 				foreach ($array as $val) {
	// 					list($k, $v) = explode('=', $val);
	// 					$value[$k] = $v;
	// 				}
	// 			} else {
	// 				$value = $array;
	// 			}
	// 			break;
	// 	}
	// 	return $value;
	// }
		//获取预支付订单
  public function getPrePayOrder($body, $out_trade_no, $total_fee){
	  $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
	  $notify_url = $this->config["notify_url"];

	  $onoce_str = $this->getRandChar(32);

		$data["appid"]            = $this->config["appid"];
		$data["body"]             = $body;
		$data["mch_id"]           = $this->config['mch_id'];
		$data["nonce_str"]        = $onoce_str;
        // $data["notify_url"]       = $notify_url;
		$data["notify_url"]       = 'http://sunsun.itboye.com/api.php/WxpayApp/return_url';
		$data["out_trade_no"]     = $out_trade_no;
		$data["spbill_create_ip"] = $this->get_client_ip();
		$data["total_fee"]        = $total_fee;
		$data["trade_type"]       = "APP";
	  $s = $this->getSign($data,false);
	  $data["sign"] = $s;

      // dump($data);exit;
      $xml = $this->arrayToXml($data);
	  $response = $this->postXmlCurl($xml, $url);

	  //将微信返回的结果xml转成数组
	  return $this->xmlstr_to_array($response);
  }
   //执行第二次签名，才能返回给客户端使用
  public function getOrder($prepayId){
    $data["appid"] = $this->config["appid"];
    $data["noncestr"] = $this->getRandChar(32);;
    $data["package"] = "Sign=WXPay";
    $data["partnerid"] = $this->config['mch_id'];
    $data["prepayid"] = $prepayId;
    $data["timestamp"] = time();
    $s = $this->getSign($data, false);
    $data["sign"] = $s;

    return $data;
  }

    /*
        生成签名
    */
    function getSign($Obj)
    {
        foreach ($Obj as $k => $v)
        {
            if($v)  $Parameters[strtolower($k)] = $v;
        }
        //签名步骤一：按字典序排序参数
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false);
        // echo "【string】 =".$String."</br>";
        //签名步骤二：在string后加入KEY
        $String = $String."&key=".$this->config['api_key'];
        // echo "<textarea style='width: 50%; height: 150px;'>$String</textarea> <br />";
        //签名步骤三：MD5加密
        $result_ = strtoupper(md5($String));
        return $result_;
    }

    //获取指定长度的随机字符串
    function getRandChar($length){
       $str = null;
       $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
       $max = strlen($strPol)-1;

       for($i=0;$i<$length;$i++){
        $str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数
       }

       return $str;
    }

    //数组转xml
    function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key=>$val)
        {
             if (is_numeric($val))
             {
                $xml.="<".$key.">".$val."</".$key.">"; 

             }
             else
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";  
        }
        $xml.="</xml>";
        return $xml; 
    }

    //post https请求，CURLOPT_POSTFIELDS xml格式
    function postXmlCurl($xml,$url,$second=30)
    {       
        //初始化curl        
        $ch = curl_init();
        //超时时间
        curl_setopt($ch,CURLOPT_TIMEOUT,$second);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if($data)
        {
            curl_close($ch);
            return $data;
        }
        else 
        { 
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error"."<br>";
            echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
            curl_close($ch);
            return false;
        }
    }

    /*
        获取当前服务器的IP
    */
    function get_client_ip()
    {
        if ($_SERVER['REMOTE_ADDR']) {
        $cip = $_SERVER['REMOTE_ADDR'];
        } elseif (getenv("REMOTE_ADDR")) {
        $cip = getenv("REMOTE_ADDR");
        } elseif (getenv("HTTP_CLIENT_IP")) {
        $cip = getenv("HTTP_CLIENT_IP");
        } else {
        $cip = "unknown";
        }
        return $cip;
    }

    //将数组转成uri字符串
    function formatBizQueryParaMap($paraMap, $urlencode)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v)
        {
            if($urlencode)
            {
               $v = urlencode($v);
            }
            $buff .= strtolower($k) . "=" . $v . "&";
        }
        $reqPar;
        if (strlen($buff) > 0) 
        {
            $reqPar = substr($buff, 0, strlen($buff)-1);
        }
        return $reqPar;
    }

    /**
     *xml转成数组
    */
    function xmlstr_to_array($xmlstr) {
      $doc = new \DOMDocument();
      $doc->loadXML($xmlstr);
      return $this->domnode_to_array($doc->documentElement);
    }
    function domnode_to_array($node) {
      $output = array();
      switch ($node->nodeType) {
       case XML_CDATA_SECTION_NODE:
       case XML_TEXT_NODE:
        $output = trim($node->textContent);
       break;
       case XML_ELEMENT_NODE:
        for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) {
         $child = $node->childNodes->item($i);
         $v = $this->domnode_to_array($child);
         if(isset($child->tagName)) {
           $t = $child->tagName;
           if(!isset($output[$t])) {
            $output[$t] = array();
           }
           $output[$t][] = $v;
         }
         elseif($v) {
          $output = (string) $v;
         }
        }
        if(is_array($output)) {
         if($node->attributes->length) {
          $a = array();
          foreach($node->attributes as $attrName => $attrNode) {
           $a[$attrName] = (string) $attrNode->value;
          }
          $output['@attributes'] = $a;
         }
         foreach ($output as $t => $v) {
          if(is_array($v) && count($v)==1 && $t!='@attributes') {
           $output[$t] = $v[0];
          }
         }
        }
       break;
      }
      return $output;
    }
}